package com.boot.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.boot.constants.RedisKeys;
import com.boot.constants.StatusConstants;
import com.boot.entity.Comment;
import com.boot.entity.Question;
import com.boot.entity.QuestionAssignment;
import com.boot.entity.User;
import com.boot.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class ApprovalNotificationTask {

    @Resource
    private IQuestionService questionService;

    @Resource
    private ICommentService commentService;

    @Resource
    private IUserService userService;

    @Resource
    private IQuestionAssignmentService questionAssignmentService;

    @Resource
    private MailService mailService;

    @Resource(name = "stringRedisTemplate")
    private StringRedisTemplate redisTemplate;

    /**
     * 每隔 2 分钟执行一次（不要太频繁，防止打扰）
     */
    @Scheduled(fixedDelay = 2_000)
    public void scanAndNotifyPendingReviews() {
        log.info("[定时任务] 开始扫描审批通过的问题与评论...");

        try {
            // 1. 处理审批通过问题
            handleApprovalQuestions();

            // 2. 处理审批通过评论
            handleApprovalComments();
        } catch (Exception e) {
            log.error("【通知任务异常】" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 扫描所有审核通过但尚未通知的问题，向被邀请的专家发送提醒
     */
    private void handleApprovalQuestions() {
        log.debug("开始处理审核通过的问题");

        QueryWrapper<Question> wrapper = new QueryWrapper<>();
        wrapper.eq("status", StatusConstants.QuestionStatus.WAITING); // 审核通过后进入 waiting 状态

        List<Question> approvedQuestions = questionService.list(wrapper);
        log.info("找到 {} 个待通知的审核通过问题", approvedQuestions.size());

        for (Question q : approvedQuestions) {
            String idKey = String.valueOf(q.getId());

            // 检查是否已经发过通知
            Boolean hasNotified = redisTemplate.opsForSet().isMember(RedisKeys.SENT_APPROVAL_NOTIFY_QUESTION, idKey);
            if (Boolean.TRUE.equals(hasNotified)) {
                continue; // 已通知，跳过
            }

            try {
                // 获取被邀请的专家列表（假设有一个中间表或字段存储邀请信息）
                List<User> experts = getInvitedExpertsForQuestion(q.getId());
                if (experts.isEmpty()) {
                    log.debug("问题 ID={} 无被邀请专家，跳过通知", q.getId());
                    // 标记为已处理，避免反复查询
                    redisTemplate.opsForSet().add(RedisKeys.SENT_APPROVAL_NOTIFY_QUESTION, idKey);
                    continue;
                }

                for (User expert : experts) {
                    if (expert.getEmail() == null || expert.getEmail().trim().isEmpty()) {
                        log.warn("专家 ID={} 无邮箱，无法发送通知", expert.getId());
                        continue;
                    }

                    String emailContent = buildQuestionApprovedToExpertEmail(expert.getUsername(), q.getTitle());
                    String subject = "📬 用户邀请您解答问题: " + truncate(q.getTitle(), 50);

                    mailService.sendHtmlMail(expert.getEmail(), subject, emailContent);
                    log.info("✅ 已向专家 {} 发送问题邀请通知，问题ID={}", expert.getUsername(), q.getId());
                }

                // 标记为已通知
                redisTemplate.opsForSet().add(RedisKeys.SENT_APPROVAL_NOTIFY_QUESTION, idKey);

            } catch (Exception e) {
                log.error("📧 发送问题审批通过通知失败（问题ID=" + q.getId() + "）：" + e.getMessage(), e);
            }
        }
    }

    /**
     * 扫描所有审核通过但尚未通知的评论，向相关用户发送提醒
     */
    private void handleApprovalComments() {
        log.debug("开始处理审核通过的评论");

        QueryWrapper<Comment> wrapper = new QueryWrapper<>();
        wrapper.eq("status", StatusConstants.CommentStatus.APPROVED); // 已通过的评论

        List<Comment> approvedComments = commentService.list(wrapper);
        log.info("找到 {} 个待通知的审核通过评论", approvedComments.size());

        for (Comment c : approvedComments) {
            String idKey = String.valueOf(c.getId());

            // 检查是否已经发过通知
            Boolean hasNotified = redisTemplate.opsForSet().isMember(RedisKeys.SENT_APPROVAL_NOTIFY_COMMENT, idKey);
            if (Boolean.TRUE.equals(hasNotified)) {
                continue; // 已通知，跳过
            }

            try {
                // 查询评论者、问题发布人、问题标题
                User commenter = userService.getById(c.getUserId());
                Question question = questionService.getById(c.getQuestionId());

                if (question == null) {
                    log.warn("评论对应的问题不存在，ID={}", c.getQuestionId());
                    redisTemplate.opsForSet().add(RedisKeys.SENT_APPROVAL_NOTIFY_COMMENT, idKey);
                    continue;
                }

                User submitter = userService.getById(question.getUserId());
                String questionTitle = question.getTitle();

                // 判断是问题发布人的评论还是专家的评论
                // 如果是问题发布人
                if (question.getUserId().equals(c.getUserId())) {
                    // 通知正在处理该问题的专家（假设存在 assignment 表，且 accepted=ACCEPTED）
                    User expert = getAssignedExpertForQuestion(c.getQuestionId());
                    if (expert == null || expert.getEmail() == null || expert.getEmail().trim().isEmpty()) continue;

                    try {
                        String content = buildCommentApprovedToExpertEmail(
                                expert.getUsername(),
                                questionTitle,
                                c.getContent(),
                                commenter != null ? commenter.getUsername() : "匿名用户"
                        );
                        String subject = "🗨️ 您处理的问题有新评论";
                        mailService.sendHtmlMail(expert.getEmail(), subject, content);
                        log.info("✅ 已通知专家 {} 关于新评论，问题ID={}", expert.getUsername(), c.getQuestionId());
                    } catch (Exception e) {
                        log.error("📧 通知专家失败（评论ID={}, 专家={}) : {}", c.getId(), expert.getUsername(), e.getMessage(), e);
                    }
                }
                // 如果是专家
                else {
                    // 通知问题发布人
                    if (submitter != null && submitter.getEmail() != null && !submitter.getEmail().trim().isEmpty()) {
                        try {
                            String content = buildCommentApprovedToSubmitterEmail(
                                    submitter.getUsername(),
                                    questionTitle,
                                    c.getContent(),
                                    commenter != null ? commenter.getUsername() : "匿名用户"
                            );
                            String subject = "💬 您的问题有新回复";
                            mailService.sendHtmlMail(submitter.getEmail(), subject, content);
                            log.info("✅ 已通知问题发布人 {}，评论ID={}", submitter.getUsername(), c.getId());
                        } catch (Exception e) {
                            log.error("📧 通知问题发布人失败（评论ID={}）: {}", c.getId(), e.getMessage(), e);
                        }
                    }
                }

                // 标记为已通知
                redisTemplate.opsForSet().add(RedisKeys.SENT_APPROVAL_NOTIFY_COMMENT, idKey);

            } catch (Exception e) {
                log.error("📧 处理评论通知时发生异常（评论ID=" + c.getId() + "）：" + e.getMessage(), e);
            }
        }
    }

    // ==================== 辅助方法：获取业务关联用户 ====================

    /**
     * 获取某问题下被邀请的专家列表
     */
    private List<User> getInvitedExpertsForQuestion(Long questionId) {
        QueryWrapper<QuestionAssignment> wrapper = new QueryWrapper<>();
        wrapper.eq("question_id", questionId)
                .isNull("accepted");
        List<QuestionAssignment> questionAssignments = questionAssignmentService.list(wrapper);

        List<Long> expertIds = new ArrayList<>();
        for (QuestionAssignment questionAssignment : questionAssignments) {
            expertIds.add(questionAssignment.getExpertId());
        }

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.in("id", expertIds)
                .eq("status", StatusConstants.UserStatus.ENABLED);
        return userService.list(userQueryWrapper);
    }

    /**
     * 获取某问题下已被分配并接受的专家（即正在处理的专家）
     */
    private User getAssignedExpertForQuestion(Long questionId) {
        QueryWrapper<QuestionAssignment> wrapper = new QueryWrapper<>();
        wrapper.eq("question_id", questionId)
                .eq("accepted", StatusConstants.AssignmentStatus.ACCEPTED)
                .last("limit 1");
        QuestionAssignment assignment = questionAssignmentService.getOne(wrapper);

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id", assignment.getExpertId())
                .eq("status", StatusConstants.UserStatus.ENABLED);
        return userService.getOne(userQueryWrapper);
    }

    // ==================== 邮件内容构建（已提供，无需修改）====================

    /**
     * 构建：问题审核通过后，提醒被用户邀请的专家 —— 用户邀请您解答问题
     */
    public String buildQuestionApprovedToExpertEmail(String expertName, String questionTitle) {
        return "<div style='font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;'>"
                + "<h2 style='color: #2196F3;'>📬 您收到一条用户邀请，请您解答问题</h2>"
                + "<p><strong>您好，" + escapeHtml(expertName) + "：</strong></p>"
                + "<p>有一位用户在提交问题时，特别邀请您作为专家进行解答。该问题已通过平台审核，现正式通知您：</p>"
                + "<blockquote style='background: #f0f8ff; border-left: 5px solid #2196F3; padding: 15px; margin: 20px 0; font-size: 1.1em;'>"
                + "“<strong>" + escapeHtml(questionTitle) + "</strong>”"
                + "</blockquote>"
                + "<p>这是一份来自用户的信任与期待。我们诚邀您登录系统查看详细内容，并考虑接受邀请给予专业回复。</p>"
                + "<p>您的专业知识将为提问者带来极大帮助！</p>"
                + "<footer style='margin-top: 30px; color: #777; font-size: 0.9em; text-align: center;'>"
                + "&copy; " + java.time.LocalDate.now().getYear() + " 系统管理平台</footer>"
                + "</div>";
    }

    /**
     * 构建：评论审核通过后，提醒问题发布人 的邮件内容
     */
    public String buildCommentApprovedToSubmitterEmail(String submitterName, String questionTitle, String commentContent, String commenterName) {
        return "<div style='font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;'>"
                + "<h2 style='color: #4CAF50;'>💬 新评论已发布</h2>"
                + "<p><strong>您好，" + escapeHtml(submitterName) + "：</strong></p>"
                + "<p>在您提出的问题 <em>“" + escapeHtml(questionTitle) + "”</em> 下，有一条新评论已通过审核：</p>"
                + "<blockquote style='background: #f9f9f9; border-left: 5px solid #ccc; padding: 15px; margin: 20px 0; font-style: italic; color: #555;'>"
                + "<strong>" + escapeHtml(commenterName) + "：</strong>"
                + escapeHtml(commentContent)
                + "</blockquote>"
                + "<p>您可以登录系统继续参与讨论或补充信息。</p>"
                + "<footer style='margin-top: 30px; color: #777; font-size: 0.9em; text-align: center;'>"
                + "&copy; " + java.time.LocalDate.now().getYear() + " 系统管理平台</footer>"
                + "</div>";
    }

    /**
     * 构建：评论审核通过后，提醒正在处理该问题的专家 的邮件内容
     */
    public String buildCommentApprovedToExpertEmail(String expertName, String questionTitle, String commentContent, String commenterName) {
        return "<div style='font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;'>"
                + "<h2 style='color: #2196F3;'>🗨️ 问题有新评论</h2>"
                + "<p><strong>您好，" + escapeHtml(expertName) + "：</strong></p>"
                + "<p>您正在处理的问题 <em>“" + escapeHtml(questionTitle) + "”</em> 收到一条新评论，请注意跟进：</p>"
                + "<blockquote style='background: #e3f2fd; border-left: 4px solid #2196F3; padding: 12px 15px; margin: 20px 0; color: #333;'>"
                + "<strong>" + escapeHtml(commenterName) + "：</strong><br/>"
                + escapeHtml(commentContent)
                + "</blockquote>"
                + "<p>建议您登录系统查看完整上下文，并适时给予专业回复。</p>"
                + "<footer style='margin-top: 30px; color: #777; font-size: 0.9em; text-align: center;'>"
                + "&copy; " + java.time.LocalDate.now().getYear() + " 系统管理平台</footer>"
                + "</div>";
    }

    // ==================== 工具方法 ====================

    private String escapeHtml(String str) {
        if (str == null) return "";
        return str.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&#x27;");
    }

    private String truncate(String str, int len) {
        if (str == null) return "";
        return str.length() <= len ? str : str.substring(0, len) + "...";
    }
}
